__author__ = 'shawhen'

from collections import OrderedDict
import re

indicator_body_regex = re.compile(r"(Q[A-Z]\w+)#{0,1}([a-zA-Z0-9_]{0,}):{0,1}([a-z]{0,})")
style_sheet_body_regex = re.compile(r'([a-zA-Z_-]{1,}):\s{0,}([a-zA-Z0-9_"/(:). -]{1,})')

def parse_style_sheet(style_sheet):
    """
    解析一个style sheet，比如: QLabel#central:pressed { color: white; }可以得到：
     1.表征的元素类型 QLabel or QWidget
     2.表征的元素名称 central
     3.表征的元素状态 pressed
     4.表征的元素内容
        color -> white
    """
    parse_result = {}

    match_result = indicator_body_regex.match(style_sheet)
    if match_result is None:
        raise ValueError
    element_type = match_result.group(1)
    element_name = match_result.group(2)
    element_state = match_result.group(3)
    element_body = style_sheet[style_sheet.find("{")+1:style_sheet.find("}")]

    parse_result["type"] = element_type
    parse_result["name"] = element_name
    parse_result["state"] = element_state
    parse_result["body"] = OrderedDict()

    body_results = style_sheet_body_regex.findall(element_body)
    for (style_sheet_key, style_sheet_value) in body_results:
        parse_result["body"][style_sheet_key] = style_sheet_value

    return parse_result

def pack_style_sheet(style_sheet):
    style_sheet_text = style_sheet["type"]
    if "name" in style_sheet and len(style_sheet["name"]) != 0:
        style_sheet_text += ("#"+style_sheet["name"])
    if "state" in style_sheet and len(style_sheet["state"]) != 0:
        style_sheet_text += (":"+style_sheet["state"])
    style_sheet_text += " {\n"
    for key, value in style_sheet["body"].items():
        style_sheet_text += (key+": "+value+";\n")
    style_sheet_text += "}"

    return style_sheet_text

def delta(widget, style_sheet, specify_widget = False, replace = True):
    """
    增量修改控件的样式，比如只修改颜色什么。。。
    :param specify_widget: 是否在样式表中指定widget_name，即用#限定
    :param replace: 指定的样式已存在时是否替换
    @note
    目前只支持单元类型单个名称单个状态
    """
    cur_style_sheet = parse_style_sheet(widget.styleSheet())
    delta_style_sheet = parse_style_sheet(style_sheet)

    for key, value in delta_style_sheet["body"].items():
        if key not in cur_style_sheet["body"] or (key in cur_style_sheet["body"] and replace is True):
            cur_style_sheet["body"][key] = value

    if specify_widget is True:
        cur_style_sheet["name"] = widget.objectName()

    if "state" in delta_style_sheet:
        if "state" not in cur_style_sheet:
            raise ValueError("state not in cur_style_sheet")
        else:
            if delta_style_sheet["state"] != cur_style_sheet["state"]:
                raise ValueError("state not same")

    new_style_sheet = pack_style_sheet(cur_style_sheet)
    widget.setStyleSheet(new_style_sheet)